package com.zaodei.rxjob.job.controller;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.zaodei.rxjob.common.annotation.Log;
import com.zaodei.rxjob.common.base.AjaxResult;
import com.zaodei.rxjob.common.enums.BusinessType;
import com.zaodei.rxjob.common.page.TableDataInfo;
import com.zaodei.rxjob.core.web.base.BaseController;
import com.zaodei.rxjob.job.admin.core.model.XxlJobGroup;
import com.zaodei.rxjob.job.admin.core.model.XxlJobInfo;
import com.zaodei.rxjob.job.admin.core.model.XxlJobLog;
import com.zaodei.rxjob.job.admin.core.schedule.XxlJobDynamicScheduler;
import com.zaodei.rxjob.job.admin.core.util.I18nUtil;
import com.xxl.job.core.biz.ExecutorBiz;
import com.xxl.job.core.biz.model.LogResult;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.glue.GlueTypeEnum;
import com.zaodei.rxjob.job.dao.XxlJobGroupDao;
import com.zaodei.rxjob.job.dao.XxlJobInfoDao;
import com.zaodei.rxjob.job.dao.XxlJobLogDao;
import com.zaodei.rxjob.job.service.NXxlJobService;

/**
 * @Title:任务日志
 * @Description:
 * @Author:wuche@laozo.com
 * @time:2019年1月19日
 */
@Controller
@RequestMapping("/job/joblog")
public class NjobLogController extends BaseController {
	private static Logger logger = LoggerFactory
			.getLogger(NjobLogController.class);
	private String prefix = "job/joblog";

	@Resource
	private XxlJobGroupDao xxlJobGroupDao;
	@Resource
	public XxlJobInfoDao xxlJobInfoDao;
	@Resource
	public XxlJobLogDao xxlJobLogDao;
	
	@Resource
	private NXxlJobService xxlJobService;

	/**
	 * 任务日志首页
	 * 
	 * @param model
	 * @param jobId
	 * @return
	 */
	@RequiresPermissions("job:joblog:view")
	@RequestMapping()
	public String joblog(Model model) {
		// 任务组
		//List<XxlJobGroup> jobGroupList = xxlJobGroupDao.findAll();
		XxlJobGroup jobGroup = new XxlJobGroup();
		jobGroup.setUserId(getUserId());
		List<XxlJobGroup> jobGroupList = xxlJobGroupDao.selectJobGroupList(jobGroup);
		model.addAttribute("JobGroupList", jobGroupList);
		model.addAttribute("GlueTypeEnum", GlueTypeEnum.values());
		return prefix + "/joblog";
	}

	/**
	 * 任务日志首页
	 * 
	 * @param model
	 * @param jobId
	 * @return
	 */
	@RequiresPermissions("job:joblog:view")
	@RequestMapping("/{jobId}")
	public String joblog(Model model, @PathVariable("jobId") int jobId) {

		// 任务组
		//List<XxlJobGroup> jobGroupList = xxlJobGroupDao.findAll();
		XxlJobGroup jobGroup = new XxlJobGroup();
		jobGroup.setUserId(getUserId());
		List<XxlJobGroup> jobGroupList = xxlJobGroupDao.selectJobGroupList(jobGroup);
		model.addAttribute("JobGroupList", jobGroupList);
		model.addAttribute("GlueTypeEnum", GlueTypeEnum.values());
		// 任务
		if (jobId > 0) {
		//	XxlJobInfo jobInfo = xxlJobInfoDao.loadById(jobId);
			XxlJobInfo  jobInfo = xxlJobService.loadJobInfo(jobId);
			model.addAttribute("jobInfo", jobInfo);
		}
		return prefix + "/joblog";
	}

	@RequestMapping("/getJobsByGroup")
	@ResponseBody
	public ReturnT<List<XxlJobInfo>> getJobsByGroup(int jobGroup) {
		List<XxlJobInfo> list = xxlJobInfoDao.getJobsByGroup(jobGroup);
		return new ReturnT<List<XxlJobInfo>>(list);
	}

	/**
	 * 获取列表
	 * 
	 * @param paramMap
	 * @return
	 */
	@RequiresPermissions("job:joblog:view")
	@RequestMapping("/list")
	@ResponseBody
	public TableDataInfo list(XxlJobLog xxlJobLog) {
		startPage();
		String filterTime =xxlJobLog.getFilterTime();
		// parse param
		String triggerTimeStartStr = "";
		String triggerTimeEndStr = "";
		if (StringUtils.isNotBlank(filterTime)) {
			String[] temp = filterTime.split(" - ");
			if (temp != null && temp.length == 2) {
				triggerTimeStartStr = temp[0];
				triggerTimeEndStr = temp[1];
				xxlJobLog.setTriggerTimeStart(triggerTimeStartStr);
				xxlJobLog.setTriggerTimeEnd(triggerTimeEndStr);
			}
		}
		
		// page query
		xxlJobLog.setUserId(getUserId());
		List<XxlJobLog> list = xxlJobLogDao.list(xxlJobLog);
		return getDataTable(list);
	}

	/**
	 * 获取单条任务详情
	 * 
	 * @param id
	 * @param model
	 * @return
	 */
	@RequiresPermissions("job:joblog:view")
	@RequestMapping("/logDetailPage/{id}")
	public String logDetailPage(@PathVariable("id") int id, Model model) {

		// base check
		XxlJobLog jobLog = xxlJobLogDao.load(id);
		if (jobLog == null) {
			throw new RuntimeException(
					I18nUtil.getString("joblog_logid_unvalid"));
		}
		model.addAttribute("triggerCode", jobLog.getTriggerCode());
		model.addAttribute("handleCode", jobLog.getHandleCode());
		model.addAttribute("executorAddress", jobLog.getExecutorAddress());
		model.addAttribute("triggerTime", jobLog.getTriggerTime().getTime());
		model.addAttribute("logId", jobLog.getId());
		return "job/joblog/detail";
	}

	@RequestMapping("/logDetailCat")
	@ResponseBody
	public ReturnT<LogResult> logDetailCat(
			@RequestParam Map<String, Object> paramMap) {
		try {
			String executorAddress = (String) paramMap.get("executorAddress");
			long triggerTime = 0;
			if (paramMap.containsKey("triggerTime")) {
				String obj = (String) paramMap.get("triggerTime");
				if (obj != null && obj.length() != 0) {
					triggerTime = Long.parseLong(obj);
				}
			}
			int logId = 0;
			if (paramMap.containsKey("logId")) {
				String obj = (String) paramMap.get("logId");
				if (obj != null && obj.length() != 0) {
					logId = Integer.parseInt(obj);
				}
			}
			int fromLineNum = 0;
			if (paramMap.containsKey("fromLineNum")) {
				String obj = (String) paramMap.get("fromLineNum");
				if (obj != null && obj.length() != 0) {
					fromLineNum = Integer.parseInt(obj);
				}
			}
			ExecutorBiz executorBiz = XxlJobDynamicScheduler
					.getExecutorBiz(executorAddress);
			ReturnT<LogResult> logResult = executorBiz.log(triggerTime, logId,
					fromLineNum);

			// is end
			if (logResult.getContent() != null
					&& logResult.getContent().getFromLineNum() > logResult
							.getContent().getToLineNum()) {
				XxlJobLog jobLog = xxlJobLogDao.load(logId);
				if (jobLog.getHandleCode() > 0) {
					logResult.getContent().setEnd(true);
				}
			}

			return logResult;
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return new ReturnT<LogResult>(ReturnT.FAIL_CODE, e.getMessage());
		}
	}

	@Log(title = "关闭正在调度任务", businessType = BusinessType.UPDATE)
	@RequestMapping("/logKill/{id}")
	@ResponseBody
	public AjaxResult logKill(@PathVariable("id") int id) {
		// base check
		XxlJobLog log = xxlJobLogDao.load(id);
		XxlJobInfo jobInfo = xxlJobInfoDao.loadById(log.getJobId());
		if (jobInfo == null) {
			return error(I18nUtil.getString("jobinfo_glue_jobid_unvalid"));
		}
		if (ReturnT.SUCCESS_CODE != log.getTriggerCode()) {
			return error(I18nUtil.getString("joblog_kill_log_limit"));
		}

		// request of kill
		ReturnT<String> runResult = null;
		try {
			ExecutorBiz executorBiz = XxlJobDynamicScheduler.getExecutorBiz(log
					.getExecutorAddress());
			runResult = executorBiz.kill(jobInfo.getId());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			runResult = new ReturnT<String>(500, e.getMessage());
		}

		if (ReturnT.SUCCESS_CODE == runResult.getCode()) {
			log.setHandleCode(ReturnT.FAIL_CODE);
			log.setHandleMsg(I18nUtil.getString("joblog_kill_log_byman") + ":"
					+ (runResult.getMsg() != null ? runResult.getMsg() : ""));
			log.setHandleTime(new Date());
			xxlJobLogDao.updateHandleInfo(log);
			return success(runResult.getMsg());
		} else {
			return error(runResult.getMsg());
		}
	}

	/**
	 * 清除日志
	 * 
	 * @param model
	 * @param jobId
	 * @return
	 */
	@RequiresPermissions("job:joblog:remove")
	@RequestMapping("/remove")
	public String joblog(Model model, @RequestParam HashMap<String, Object> map) {
		// 执行器列表
		model.addAttribute("jobGroupText", map.get("jobGroupText"));
		model.addAttribute("jobGroup", map.get("jobGroup"));
		model.addAttribute("jobIdText", map.get("jobIdText"));
		model.addAttribute("jobId", map.get("jobId"));
		model.addAttribute("projectId", map.get("projectId"));
		model.addAttribute("projectText", map.get("projectText"));
		return prefix + "/deletelog";
	}

	@Log(title = "清除调度日志", businessType = BusinessType.DELETE)
	@RequestMapping("/clearLog")
	@ResponseBody
	public AjaxResult clearLog(@RequestParam Map<String, Object> paramMap) {
		int type = 1;
		if (paramMap.containsKey("type")) {
			String obj = (String) paramMap.get("type");
			if (obj != null && obj.length() != 0) {
				type = Integer.parseInt(obj);
			}
		}
		int jobId = 0;
		if (paramMap.containsKey("jobId")) {
			String obj = (String) paramMap.get("jobId");
			if (obj != null && obj.length() != 0) {
				jobId = Integer.parseInt(obj);
			}
		}
		int jobGroup = 0;
		if (paramMap.containsKey("jobGroup")) {
			String obj = (String) paramMap.get("jobGroup");
			if (obj != null && obj.length() != 0) {
				jobGroup = Integer.parseInt(obj);
			}
		}
		int projectId = 0;
		if (paramMap.containsKey("projectId")) {
			String obj = (String) paramMap.get("projectId");
			if (obj != null && obj.length() != 0) {
				projectId = Integer.parseInt(obj);
			}
		}
		Date clearBeforeTime = null;
		int clearBeforeNum = 0;
		if (type == 1) {
			clearBeforeTime = DateUtils.addMonths(new Date(), -1); // 清理一个月之前日志数据
		} else if (type == 2) {
			clearBeforeTime = DateUtils.addMonths(new Date(), -3); // 清理三个月之前日志数据
		} else if (type == 3) {
			clearBeforeTime = DateUtils.addMonths(new Date(), -6); // 清理六个月之前日志数据
		} else if (type == 4) {
			clearBeforeTime = DateUtils.addYears(new Date(), -1); // 清理一年之前日志数据
		} else if (type == 5) {
			clearBeforeNum = 1000; // 清理一千条以前日志数据
		} else if (type == 6) {
			clearBeforeNum = 10000; // 清理一万条以前日志数据
		} else if (type == 7) {
			clearBeforeNum = 30000; // 清理三万条以前日志数据
		} else if (type == 8) {
			clearBeforeNum = 100000; // 清理十万条以前日志数据
		} else if (type == 9) {
			clearBeforeNum = 0; // 清理所有日志数据
		} else {
			return error(I18nUtil.getString("joblog_clean_type_unvalid"));
		}
        //添加userId清除自己所管理项目底下的执行器日志
		xxlJobLogDao.clearLog(jobGroup, jobId,getUserId(),projectId, clearBeforeTime, clearBeforeNum);
		return toAjax(true);
	}
}
